package com.zkh.myutils.expression;

import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

import com.zkh.myutils.io.log.Logger;
import com.zkh.myutils.system.ConfigLoader;
import com.zkh.myutils.utils.DateUtils;
import com.zkh.myutils.utils.Utils;

/**
 * 表达式对象。表达式是对一段字符串求值操作。值的类型只包含三种，分别是数字（BigDecimal）、字符（String）和布尔值（Boolean）
 * <p>表达式支持的操作符如下：</p>
 * <b>+ - * / % > < == >= <= != and or not 负号 函数</b>
 * <p>其对应的内部符号为：</p>
 * <b>+ - * / % > < =  }  {  #  &   |   ~  ^  $</b>
 */
public class Expression {
	/**
	 * 是否展示表达式日志
	 */
	private final static boolean showExpressionLog = "true".equals(ConfigLoader.getString("expand.showExpressionLog", true));
	/**
	 * call函数自定义处理类前缀
	 */
	private final static String expressionHandlerPrefix = ConfigLoader.getString("expand.expressionHandlerPrefix", "", true);
	/**
	 * 表达式缓存
	 */
	private final static Map<String, Expression> cacheMap;
	/**
	 * 所有操作符
	 */
	private final static char[] operators = {'(', '*', '/', '%', '+', '-', '>', '<', '=', '{', '}', '#', '~', '&', '|', ')', '^'};
	/**
	 * 所有操作符的优先级，从左往右优先级从高到低
	 */
	private static final List<String> priorityList = Arrays.asList("(", "^", "*/%", "+-", "><={}#", "~", "&", "|", ")");
	/**
	 * 关键词（含函数）
	 */
	private final static String[] keywords = {"and", "or", "not", "in", "case", "decode", "length", "empty", "formatDate", "substring", "call"};
	/**
	 * 关键词替换字符
	 */
	private final static String[] keywordReplaces = {"&", "|", "~", "$i", "$c", "$d", "$l", "$e", "$f", "$s", "$a"};
	/**
	 * 双字符操作符
	 */
	private final static char[] dbOpers = {'>', '<', '=', '!'};
	private final static char[] dbOperSigns = {'}', '{', '=', '#'};
	/**
	 * 逆波兰表达式栈
	 */
	private LinkedList<Element> suffixStack = new LinkedList<>();
	/**
	 * 非法字符
	 */
	private static char[] invalidChars = {'{', '}', '#', '&', '|', '~', '$', '^'};
	
	//初始化
	static {
		//初始化表达式缓存容器
		cacheMap = new ConcurrentHashMap<>();
	}
	
	/**
	 * 创建一个表达式实体
	 * @param expression 表达式
	 */
	public static Expression newInstance(String expression) {
		return newInstance(expression, true);
	}
	
	/**
	 * 创建一个表达式实体
	 * @param expression 表达式
	 */
	static Expression newInstance(String expression, boolean checkChar) {
		//为空
		if(expression==null || (expression = expression.trim()).isEmpty()) {
			throw new ExpressionException("表达式不能为空");
		}
		//唯一标识
		String unique = Utils.md5(expression);
		//获取已有表达式
		Expression exp = cacheMap.get(unique);
		//不存在，则创建
		if(exp==null) {
			//日志
			if(showExpressionLog) {
				Logger.debug("原始表达式：{}", expression);
			}
			//创建时加同步锁
			synchronized (unique.intern()) {
				//预处理表达式
				expression = preDeal(expression.replace("&gt;",">").replace("&lt;","<"), checkChar);
				//日志
				if(showExpressionLog) {
					Logger.debug("格式化表达式：{}", expression);
				}
				//创建并保存
				cacheMap.put(unique, exp = new Expression().parse(expression));
				//解析完成
				if(showExpressionLog) {
					Logger.debug("解析表达式：{}", exp.suffixStack);
				}
			}
		}
		//返回
		return exp;
	}
	
	/**
	 * 预处理表达式。将多字符操作符转换为单字符操作符，便于处理
	 * @param expression 待处理表达式
	 */
	private static String preDeal(String expression, boolean checkChar) {
		//检查非法字符，避免与内置符号冲突
		if(checkChar) {
			for(char c: invalidChars) {
				if(expression.indexOf(c)>-1) {
					throw new ExpressionException("非法字符：" + c);
				}
			}
		}
		//最终字符
		StringBuilder sb = new StringBuilder();
		//临时字符
		StringBuilder temp = new StringBuilder();
		//转字符数组
		char[] chars = expression.toCharArray();
		//长度
		int len = chars.length, tlen = 0;
		//指针、上一字符是否为操作符标识（不含空格）、双字符操作符索引
		int p = 0, lastOper = -1, d = -1;
		//开始遍历
		while(p<len) {
			//当前字符
			char curr = chars[p];
			//字符串
			if(curr=='\'' || curr=='"') {
				//获取字符串
				p = Element.getString(p, len, curr, chars, temp, true);
				//保存字符
				sb.append(curr).append(temp.toString()).append(curr);
				//清除
				temp.setLength(0);
				//移动指针
				p++;
				//跳过
				continue;
			}
			//操作符
			boolean oper = isOperator(curr);
			//空白
			boolean blank = !oper && isSpace(curr);
			//非空白，保存
			if(!oper && !blank) {
				temp.append(curr);
			}
			//判断负号
			if(curr=='-' && (lastOper==-1 || lastOper==1 && sb.charAt(sb.length()-1)!=')')) {
				sb.append('^');
			}//不是负号
			else {
				//当前是分隔符（操作符、空格和逗号均为分隔符）
				if(oper || blank || curr==',') {
					//查找双字符操作符
					if(curr=='=' && (tlen=sb.length()-1)>-1) {
						//上一字符
						d = findDbOper(sb.charAt(tlen));
						//找到
						if(d>-1) {
							sb.setCharAt(tlen, dbOperSigns[d]);
						}else if((tlen=temp.length()-1)>-1){
							//从temp中查找
							d = findDbOper(temp.charAt(tlen));
							//找到
							if(d>-1) {
								temp.setCharAt(tlen, dbOperSigns[d]);
								//保存
								sb.append(temp.toString());
								//清空容器
								temp.setLength(0);
							}
						}
					}
					//没有找到
					if(d==-1) {
						//获取字符
						String str = temp.toString();
						//不为空
						if(!str.isEmpty()) {
							//查找关键词
							int kw = isKeyWord(str);
							//关键词
							if(kw>-1) {
								sb.append(keywordReplaces[kw]);
							}else {
								sb.append(str);
							}
							//清空容器
							temp.setLength(0);
						}
						//保存当前操作符
						if(oper) {
							sb.append(curr);
						}
					}else {
						//重置标识
						d = -1;
					}
				}
			}
			//不为空格
			if(!blank) {
				//上一字符
				lastOper = oper ? 1 : 0;
			}
			//移动指针
			p++;
		}
		//还有字符
		String str = temp.toString();
		//不为空
		if(!str.isEmpty()) {
			//查找关键词
			int kw = isKeyWord(str);
			//关键词
			if(kw>-1) {
				sb.append(keywordReplaces[kw]);
			}else {
				sb.append(str);
			}
			//清空容器
			temp.setLength(0);
		}
		//返回
		return sb.toString();
	}

	//私有化构造方法
	private Expression() {}
	
	/**
	 * 解析表达式，并转换为逆波兰表达式。
	 * 
	 * 
	 * 规则就是，用当前的符号与栈顶的符号比较优先级，如果当前符号优先级小于栈顶符号的优先级，则把栈里面的符号都弹出来。
	 * 括号的操作除外，括号是左括号优先级最高，不管跟啥比，
	 * 都是入栈；右括号是优先级最低，跟啥比都是弹出栈内符号，但只弹到跟它匹配的最近的那个左括号。
	 * 
	 * @param expression 待处理表达式
	 */
	private Expression parse(String expression) {
		//操作符栈（所有操作符用一个字符来表示）
		LinkedList<Character> operatorStack = new LinkedList<Character>();
		//获取字符数组
		char[] chars = expression.toCharArray();
		//字符长度
		int len = chars.length;
		//临时字符串
		StringBuilder sb = new StringBuilder();
		//遍历
		for(int i=0; i<len; i++) {
			//当前字符
			char curr = chars[i];
			//是否是操作符
			int lvl = getOperLvl(curr);
			//操作符
			if(lvl>0) {
				//最高级（左括号）
				if(lvl==1) {
					//压入操作符栈
					operatorStack.add(curr);
				}//最低级（右括号）
				else if(lvl==priorityList.size()) {
					//匹配标识
					boolean matched = false;
					//处理符号栈，查找左括号
					while(!operatorStack.isEmpty()) {
						//弹出栈顶操作符
						Character oper = operatorStack.pollLast();
						//如果匹配到左括号，直接跳出循环
						if(oper=='(') {
							//匹配标识
							matched = true;
							break;
						}
						//压栈
						suffixStack.add(new Element(oper, Type.OPERATOR));
					}
					//未找到左括号
					if(!matched) {
						throw new ExpressionException("表达式解析失败：括号异常");
					}
				}//中间级
				else {
					//处理符号栈
					while(!operatorStack.isEmpty()) {
						//弹出栈顶操作符
						Character oper = operatorStack.pollLast();
						//压栈
						if(oper=='(' || isLowerer(lvl, oper)) {
							operatorStack.add(oper);break;
						}
						//其它直接压入最终栈
						suffixStack.add(new Element(oper, Type.OPERATOR));
					}
					//当前符号栈
					operatorStack.add(curr);
				}
			}
			//字符串（单引号或双引号）
			else if(curr=='\'' || curr=='"') {
				//获取字符串
				i = Element.getString(i, len, curr, chars, sb, false);
				//入栈
				suffixStack.add(new Element(sb, Type.STRING));
				//清空
				sb.setLength(0);
			}
			//数字
			else if(curr>='0' && curr<='9') {
				//保存字符
				sb.append(curr);
				//获取剩余数字
				i = Element.getNumber(i, len, chars, sb);
				//入栈
				suffixStack.add(new Element(sb, Type.NUMBER));
				//清空
				sb.setLength(0);
			}//函数
			else if(curr=='$') {
				//解析函数
				Element fun = Element.parseFunction(i, len, chars, sb);
				//保存索引
				i = fun.getIndex();
				//入栈
				suffixStack.add(fun);
				//清空
				sb.setLength(0);
			}
			//变量或true或false
			else {
				//保存字符
				sb.append(curr);
				//获取变量元素对象
				Element element = Element.getVariable(i, len, curr, chars, sb, next->getOperLvl(next)>0);
				//对象入栈
				suffixStack.add(element);
				//保存索引
				i = element.getIndex();
				//清空
				sb.setLength(0);
			}
		}
		//剩余操作符入栈
		while(!operatorStack.isEmpty()) {
			suffixStack.add(new Element(operatorStack.pollLast(), Type.OPERATOR));
		}
		//返回当前对象
		return this;
	}
	
	/**
	 * 获取操作符的优先级数
	 * @param c 当前字符
	 * @return 操作符的优先级数
	 */
	static int getOperLvl(char c) {
		//默认级别为-1
		int lvl = -1;
		//遍历操作符（到目前为止，负号优先级仅低于括号）
		for(int i=1,len=priorityList.size(); i<=len; i++) {
			//找到操作符
			if(priorityList.get(i-1).indexOf(c)>-1) {
				lvl = i;break;
			}
		}
		//返回级别
		return lvl;
	}
	
	/**
	 * 判断当前字符的优先级是否小于指定优先级
	 * @param level 指定优先级
	 * @param t 当前字符
	 */
	private boolean isLowerer(int lvl, char t) {
		//获取当前字符的优先级并比较
		return getOperLvl(t) > lvl;
	}
	
	/**
	 * 求值。无参数。
	 */
	public Object execute() {
		return execute(new HashMap<>());
	}
	
	/**
	 * 求值
	 * @param params 参数为键值对，依次为{key1, value1, key2, value2[,..., keyN, valueN]}
	 */
	public Object execute(Object... params) {
		return execute(Utils.getMap(new HashMap<String, Object>(), params));
	}
	
	/**
	 * 求值
	 * @param params 参数
	 */
	public Object execute(Map<String, ?> params) {
		//检查空
		Objects.requireNonNull(params);
		//复制一个全新栈，不影响原来栈
		LinkedList<Element> stack = new LinkedList<>(suffixStack);
		//缓存值
		Map<String, Element> dataCacheMap = new HashMap<>();
		//当前指针
		int i = 0;
		//遍历
		while(i < stack.size()) {
			//获取当前
			Element elem = stack.get(i);
			//如果是操作符
			if(elem.getType() == Type.OPERATOR) {
				//取前两个数，用于计算
				Element r = stack.remove(--i);
				Element l = elem.getOperator()=='~' || elem.getOperator()=='^' ? null : stack.remove(--i);
				//如果是变量，则处理变量
				r = getVariableValue(r, params, dataCacheMap);
				l = getVariableValue(l, params, dataCacheMap);
				//计算结果值
				stack.set(i, calcValue(l, r, elem.getOperator()));
			}//函数
			else if(elem.getType() == Type.FUNCTION || elem.getType() == Type.VARIABLE) {
				//计算结果值
				stack.set(i, getVariableValue(elem, params, dataCacheMap));
			}
			//移动指针
			i++;
		}
		//获取结果值
		return stack.get(0).getValue();
	}

	/**
	 * 获取变量值
	 * @param element Element对象
	 * @param params 参数
	 * @param dataCacheMap 缓存数据
	 */
	private Element getVariableValue(Element element, Map<String, ? extends Object> params, Map<String, Element> dataCacheMap) {
		//解析函数
		if(element!=null && element.getType()==Type.FUNCTION) {
			element = callFun(element, params, dataCacheMap);
		}//表达式
		else if(element!=null && element.getType()==Type.EXPRESSION) {
			//解析值
			Object value = element.getExpressionValue(params);
			//元素对象
			return new Element(value, value instanceof Number ? Type.NUMBER : (value instanceof Boolean ? Type.BOOLEAN : (value instanceof String ? Type.STRING : Type.OBJECT)));
		}
		//不是变量，直接返回
		if(element==null || element.getType()!=Type.VARIABLE) {
			return element;
		}
		/** 处理变量（最终只保留字符串，布尔值和数字） **/
		//key
		String key = element.getStringValue();
		//获取缓存
		Element cache = dataCacheMap.get(key);
		//存在，直接返回
		if(cache!=null) {
			return cache;
		}
		//解析值
		Object value = Utils.parseValue(key, params);
		//元素对象
		Element e = new Element(value, value instanceof Number ? Type.NUMBER : (value instanceof Boolean ? Type.BOOLEAN : (value instanceof String ? Type.STRING : Type.OBJECT)));
		//缓存值
		dataCacheMap.put(key, e);
		//返回值
		return e;
	}
	
	/**
	 * 调用函数获取返回值
	 * @param func 函数对象
	 * @param params 参数
	 * @param dataCacheMap 缓存容器
	 */
	private Element callFun(Element func, Map<String, ?> params, Map<String, Element> dataCacheMap) {
		//获取元素
		List<Element> elems = func.getFunctionElement();
		//长度
		int elemLen = elems.size();
		//临时变量
		Element temp; Object value;
		//获取变量值
		temp = getVariableValue(elems.get(0), params, dataCacheMap);
		//获取值
		value = temp.getType()==Type.EXPRESSION ? temp.getExpressionValue(params) : temp.getValue();
		//函数类型
		switch (func.getFunctionName()) {
			//EMPTY函数
			case 'e':
				//判断空
				return new Element(Utils.isEmpty(value), Type.BOOLEAN);
			//LENGTH函数
			case 'l':
				//结果值
				int length = 0;
				//字符
				if(value instanceof String) {
					length = ((String) value).length();
				}
				//集合
				else if(value instanceof Collection) {
					length = ((Collection<?>) value).size();
				}
				else if(value instanceof Map) {
					length = ((Map<?, ?>) value).size();
				}
				//数组
				else if(value.getClass().isArray()) {
					length = Array.getLength(value);
				}
				//其它默认转字符再判断
				else {
					length = value.toString().length();
				}
				//判断空
				return new Element(length, Type.NUMBER);
			//IN函数
			case 'i':
				//遍历
				for(int i=1; i<elemLen; i++) {
					if(Objects.equals(value, elems.get(i).getValue())) {
						return new Element(true, Type.BOOLEAN);
					}
				}
				return new Element(false, Type.BOOLEAN);
			//DECODE函数
			case 'd':
				//遍历
				if(elemLen<4 || elemLen%2==1) {
					throw new ExpressionException("decode函数参数个数异常：至少4个且需包含else分支");
				}
				//遍历
				for(int i=2; i<elemLen-1; i+=2) {
					if(Objects.equals(value, getValue(elems.get(i-1), params, dataCacheMap))) {
						return getVariableValue(elems.get(i), params, dataCacheMap);
					}
				}
				//未匹配到，取else
				return getVariableValue(elems.get(elemLen-1), params, dataCacheMap);
			//CASE函数
			case 'c':
				//遍历
				if(elemLen<3 || elemLen%2==0) {
					throw new ExpressionException("case函数参数个数异常：至少3个且需包含else分支");
				}
				//遍历
				for(int i=1; i<elemLen-1; i+=2) {
					//第一个不用重复解析
					if(i!=1) {
						//获取变量值
						temp = getVariableValue(elems.get(i-1), params, dataCacheMap);
						//获取值
						value = temp.getType()==Type.EXPRESSION ? temp.getExpressionValue(params) : temp.getValue();
					}
					//检查类型
					if(!(value instanceof Boolean)) {
						throw new ExpressionException("case函数用来判断条件的参数项值不是布尔类型");
					}
					//为true
					if((Boolean) value) {
						return getVariableValue(elems.get(i), params, dataCacheMap);
					}
				}
				//未匹配到，取else
				return getVariableValue(elems.get(elemLen-1), params, dataCacheMap);
			//formatDate函数
			case 'f':
				//第二个参数
				String format = elemLen>1 ? elems.get(1).getStringValue() : "yyyy-MM-dd";
				//第一个参数是Date类型
				if(value instanceof Date) {
					return new Element(DateUtils.getString((Date) value, format), Type.STRING);
				}
				//字符串
				if(value instanceof String) {
					return new Element(DateUtils.getDate((String) value, format), Type.OBJECT);
				}
				//其它类型
				throw new ExpressionException("formatDate函数第一个参数必须是Date或String类型");
			//substring函数
			case 's':
				//长度
				if(elemLen<2) {
					throw new ExpressionException("substring函数至少需要两个参数");
				}
				//检查类型
				if(!(value instanceof String)) {
					throw new ExpressionException("substring函数只能操作字符串");
				}
				//开始位置
				Element startElem = elems.get(1);
				//结束位置
				Element endElem = elemLen>=3 ? elems.get(2) : null;
				//检查类型
				if(startElem.getType()!=Type.NUMBER || (endElem!=null && endElem.getType()!=Type.NUMBER)) {
					throw new ExpressionException("substring函数第二个和第三个参数必须是数字");
				}
				//值
				String v = value.toString();
				//开始
				int start = startElem.getNumberValue().intValue();
				//取值
				return new Element(endElem==null ? v.substring(start) : v.substring(start, endElem.getNumberValue().intValue()), Type.STRING);
			//call函数
			case 'a':
				if(temp.getType()!=Type.STRING) {
					throw new ExpressionException("call函数第一个参数必须是字符串，指定要调用的方法");
				}
				//当前值
				String val = (String) value;
				//获取分隔符位置
				int sep = val.lastIndexOf('.');
				try {
					//自定义处理方法
					String className, methodName;
					//没有点
					if(sep==-1) {
						//为空
						if(expressionHandlerPrefix.isEmpty()) {
							throw new ExpressionException("请指定扩展配置项：expressionHandlerPrefix");
						}
						//类名和方法名
						className = expressionHandlerPrefix;
						methodName = val;
					}
					//是否是全类名
					else if(val.indexOf('.')==sep) {
						//类名和方法名
						className = (expressionHandlerPrefix.isEmpty() ? "" : (expressionHandlerPrefix + ".")) + val.substring(0, sep);
						methodName = val.substring(sep+1);
					}else {
						//类名和方法名
						className = val.substring(0, sep);
						methodName = val.substring(sep+1);
					}
					//反射方法
					Method method = Class.forName(className).getMethod(methodName, Object[].class);
					//获取参数
					List<Object> paramList = new ArrayList<>();
					//遍历参数
					for(int i=1; i<elemLen; i++) {
						//获取值
						paramList.add(getValue(getVariableValue(elems.get(i), params, dataCacheMap), params, dataCacheMap));
					}
					//调用目标方法
					Object rtn = method.invoke(null, (Object) paramList.toArray());
					//返回
					if(rtn==null) {
						return new Element(null, Type.NULL);
					}
					//字符串
					if(rtn instanceof String) {
						return new Element(rtn, Type.STRING);
					}
					//数字
					if(rtn instanceof Number) {
						return new Element(rtn, Type.NUMBER);
					}
					//布尔
					if(rtn instanceof Boolean) {
						return new Element((boolean) rtn, Type.BOOLEAN);
					}
					//其它默认为对象
					return new Element(rtn, Type.OBJECT);
				}catch (ClassNotFoundException | NoSuchMethodException e) {
					throw new ExpressionException("call函数指定的自定义处理方法不存在", e);
				}catch (IllegalAccessException | IllegalArgumentException e) {
					throw new ExpressionException("call函数指定的自定义处理方法调用失败", e);
				}catch (InvocationTargetException e) {
					throw new ExpressionException(e);
				}
			default:
				break;
		}
		//返回结果
		return temp;
	}
	
	/**
	 * 获取值
	 */
	private Object getValue(Element element, Map<String, ?> params, Map<String, Element> dataCacheMap) {
		//函数
		if(element.getType()==Type.FUNCTION) {
			return callFun(element, params, dataCacheMap).getValue();
		}
		//表达式
		if(element.getType()==Type.EXPRESSION) {
			return element.getExpressionValue(params);
		}
		return element.getValue();
	}

	/**
	 * 获取值
	 * @param left 左边值
	 * @param right 右边值
	 * @param operator 操作符
	 */
	private Element calcValue(Element left, Element right, char operator) {
		//转换操作符
		char o = operator;
		//按符号计算
		switch (operator) {
			//加
			case '+':
				return left.getType()==Type.NUMBER && right.getType()==Type.NUMBER ?
						new Element(left.getNumberValue().add(right.getNumberValue()), Type.NUMBER) :
							new Element("" + left + right, Type.STRING);
			case '-':
				checkNumber(left, right, operator);
				return new Element((left.getNumberValue().subtract(right.getNumberValue())), Type.NUMBER);
			case '*':
				checkNumber(left, right, operator);
				return new Element((left.getNumberValue().multiply(right.getNumberValue())), Type.NUMBER);
			case '/':
				checkNumber(left, right, operator);
				return new Element((left.getNumberValue().divide(right.getNumberValue(), 15, RoundingMode.HALF_UP)), Type.NUMBER);
			case '%':
				checkNumber(left, right, operator);
				return new Element((left.getNumberValue().remainder(right.getNumberValue())), Type.NUMBER);
			//负
			case '^':
				checkNumber(null, right, operator);
				return new Element(right.getNumberValue().multiply(BigDecimal.valueOf(-1)), Type.NUMBER);
			case '>':
			case '<':
			case '=':
			case '}':
			case '{':
			case '#':
				//等于或不等于，可以判断null
				if(o=='=' || o=='#') {
					//左右是否为null
					boolean leftNull = left.getValue()==null, rightNull = right.getValue()==null;
					//均为null
					if(leftNull && rightNull) {
						return new Element(o=='=', Type.BOOLEAN);
					}//其中一个为null
					else if(leftNull || rightNull) {
						return new Element(o=='#', Type.BOOLEAN);
					}
				}
				//比较符
				int c;
				//字符串
				if(left.getType()==Type.STRING && right.getType()==Type.STRING) {
					c = left.getStringValue().compareTo(right.getStringValue());
				}//数字
				else if(left.getType()==Type.NUMBER && right.getType()==Type.NUMBER) {
					c = left.getNumberValue().compareTo(right.getNumberValue());
				}else {
					throw new ExpressionException("非法运算：" + (o=='}'?">=":(o=='{'?"<=":(o=='#'?"!=":String.valueOf(o)))) + "，计算对象：" + left.getValue() + "，" + right.getValue());
				}
				//计算
				boolean res = o=='>'?c>0:(o=='<'?c<0:(o=='='?c==0:(o=='}'?c>-1:(o=='{'?c<1:c!=0))));
				//返回结果
				return new Element(res, Type.BOOLEAN);
			case '&':
			case '|':
				if(left.getType()!=Type.BOOLEAN || right.getType()!=Type.BOOLEAN) {
					throw new ExpressionException("非法运算：" + (o=='&'?"and":"or") + "，计算对象：" + left.getValue() + "，" + right.getValue());
				}
				//获取值
				boolean l = left.getBooleanValue(), r = right.getBooleanValue();
				//返回
				return new Element(o=='&' ? (l && r) : (l || r), Type.BOOLEAN);
			case '~':
				if(right.getType()!=Type.BOOLEAN) {
					throw new ExpressionException("非法运算：not，计算对象：" + right.getValue());
				}
				return new Element(!right.getBooleanValue(), Type.BOOLEAN);
			default:
				throw new ExpressionException("错误的操作符：" + o);
		}
	}
	
	/**
	 * 检查数字
	 */
	private void checkNumber(Element left, Element right, char operator) {
		//仅右边且不为数字
		if(left==null && right.getType()!=Type.NUMBER) {
			throw new ExpressionException("非法运算：" + operator + "，计算对象：" + right.getValue());
		}
		//左右两边且均存在不为数字的情况
		if(left!=null && (left.getType()!=Type.NUMBER || right.getType()!=Type.NUMBER)) {
			throw new ExpressionException("非法运算：" + operator + "，计算对象：" + left.getValue() + "，" + right.getValue());
		}
	}
	
	/**
	 * 判断指定字符串是否是关键词
	 * @param string 指定字符
	 */
	private static int isKeyWord(String string) {
		//转小写
		string = string.toLowerCase();
		//遍历关键词
		for(int i=0,len=keywords.length; i<len; i++) {
			//匹配到
			if(keywords[i].equalsIgnoreCase(string)) {
				return i;
			}
		}
		//未匹配到
		return -1;
	}
	
	/**
	 * 判断指定字符是否是空白符
	 * @param c 指定字符
	 */
	private static boolean isSpace(char c) {
		return c<=' ';
	}
	
	/**
	 * 判断指定字符是否操作符
	 * @param operator 指定字符
	 */
	private static boolean isOperator(char operator) {
		//遍历操作符
		for(char o: operators) {
			//匹配到
			if(o==operator) {
				return true;
			}
		}
		//未匹配到
		return false;
	}
	
	/**
	 * 查找双字符操作符
	 * @param c 指定字符
	 */
	private static int findDbOper(char c) {
		//遍历
		for(int i=0; i<4; i++) {
			//找到
			if(c==dbOpers[i]) {
				return i;
			}
		}
		//没有找到
		return -1;
	}
}
